
window.onload = function() {
    var vm = new Vue({
        el: '#canvas',
        data: {
            svg: {
                horizonNum: 20, //背景框个数
                verticalNum: 20, //背景框个数
                space: 10, //背景框间距,
                open: '',
                end: '',
                width: '',
                height: '',
                xmlns: 'http://www.w3.org/2000/svg'
            },
            position :{
                clientX:0,//鼠标拖动过程中x轴位置
                clientY:0,//鼠标拖动过程中y轴位置
                $clientX:0,//鼠标释放时x轴位置
                $clientY:0//鼠标释放时y轴位置
            },
            rect: {
                width: 0,
                height: 0,
                strokeWidth: 0.5,
                x: 0,
                y: 0
            },
            layout: { //最小布局块
                left: 0,
                top: 0,
                offsetLeft: 0,
                offsetTop: 0,
                originOffsetLeft: 0,
                originOffsetTop: 0,
                col: 4,
                row: 4,
                originCol: 4,
                originRow: 4,
                width: 0,
                height: 0,
                ids: [],
                block: []
            },
            specify:true,
            layoutList: []
        },
        mounted() {
            window.onresize = () => {
                this.init();
            }
        },
        created() {
            this.init();
        },
        methods: {
            //初始化
            init() {
                $(document).ready(() => {

                    if (this.getScroll().scrollY) { //有垂直滚动条
                        //背景框宽度

                        this.svg.width = $('.canvas').width() + this.getScrollbarWidth();
                    } else {
                        //背景框宽度
                        this.svg.width = $('.canvas').width();
                    }
                    this.svg.height = Math.round(68 * this.svg.width / 1880); //背景框高度
                    this.svg.open = `<svg xmlns='${this.svg.xmlns}' width='${this.svg.width}' height='${this.svg.height}'>`;
                    this.svg.end = '</svg>';
                    this.initLayout();
                    this.initBackground();
                });
            },
            //获取滚动条宽度
            getScrollbarWidth() {
                let oP = document.createElement('p');
                const styles = {
                    width: '100px',
                    height: '100px',
                    overflowY: 'scroll'
                }
                let scrollbarWidth;

                for (let i in styles) {
                    oP.style[i] = styles[i];
                }

                document.body.appendChild(oP);
                scrollbarWidth = oP.offsetWidth - oP.clientWidth;
                oP.remove();
                return scrollbarWidth;
            },
            //获取滚动
            getScroll(el) {
                let elems = el ? [el] : [document.documentElement, document.body];
                let scrollX = false,
                    scrollY = false;
                for (let i = 0; i < elems.length; i++) {
                    let o = elems[i];
                    // test horizontal
                    let sl = o.scrollLeft;
                    o.scrollLeft += (sl > 0) ? -1 : 1;
                    o.scrollLeft !== sl && (scrollX = scrollX || true);
                    o.scrollLeft = sl;
                    // test vertical
                    let st = o.scrollTop;
                    o.scrollTop += (st > 0) ? -1 : 1;
                    o.scrollTop !== st && (scrollY = scrollY || true);
                    o.scrollTop = st;
                }
                // ret
                return {
                    scrollX: scrollX,
                    scrollY: scrollY
                };
            }, //初始化布局
            initLayout() {
                $(document).ready(() => {
                    const horizonNum = this.svg.horizonNum;
                    this.layoutList.forEach((layout) => {
                        const width = this.svg.width / horizonNum;
                        const height = this.svg.height;

                        layout.width = width * layout.col - layout.col - this.svg.space;
                        layout.height = height * layout.row - this.svg.space - layout.row;
                        layout.left = layout.offsetLeft * (width - 1) + this.svg.space;
                        layout.top = layout.offsetTop * (height - 1) + 0.5 * this.svg.space;
                        layout.originCol = layout.col;
                        layout.originRow = layout.row;
                        layout.originOffsetLeft = layout.offsetLeft;
                        layout.originOffsetTop = layout.offsetTop;

                    });

                });

            },
            //初始化背景
            initBackground() {
                $(document).ready(() => {
                    const horizonNum = this.svg.horizonNum;
                    const verticalNum = this.svg.verticalNum;
                    let rectList = [];
                    for (let i = 0; i < verticalNum; i++) {
                        const x = (this.svg.width / horizonNum) * i + this.svg.space;
                        const width = (this.svg.width / horizonNum) - this.svg.space;
                        this.rect.x = x;
                        this.rect.y = this.svg.space;
                        this.rect.width = width;
                        this.rect.height = this.svg.height - this.svg.space;
                        let rect = encodeURI(`<rect stroke=\'#999\' stroke-width=\'${this.rect.strokeWidth}\' fill=\'none\' x=\'${this.rect.x}\' y=\'${this.rect.y}\' width=\'${this.rect.width}\' height=\'${this.rect.height}\'/>`);
                        rectList.push(rect);
                    }

                    $('.canvas').css('background', `url(\"data:image/svg+xml;utf8,${this.svg.open}${rectList.join('')}${this.svg.end}\") 0px 0px /contain repeat-y`);
                    $('.canvas').css('min-height', `${(this.svg.height)*verticalNum-verticalNum}px`);
                });
            },
            plain(obj){
            	return JSON.parse(JSON.stringify(obj));
            },
            //添加布局
            addLayout() {
                //console.log('addLayout()');
	            let position = this.getEmptyPosition();
	            let layout = this.plain(this.layout);
	            if(position){
	                layout.offsetLeft = position.offsetLeft;
	                layout.offsetTop = position.offsetTop;
	                this.layoutList.push(layout);
	                this.initLayout();
	                this.initBackground();
	            }else {
	                this.svg.verticalNum += this.layout.row;
	                this.initLayout();
	                this.initBackground();
	                //console.error('没有可用坐标点');
	                this.addLayout();
	            }
	            this.specify = false;
            },
             //删除布局
	        delLayout(layout) {
	            const index = this.layoutList.indexOf(layout);
	            this.layoutList.splice(index,1);
	            this.specify = false;
	            //重新计算画布高度
	            this.svg.verticalNum = this.getVerticalNum();
	            this.initBackground();
	        },
            //计算布局大小
            layoutSizePosition(layout) {
                return `width: ${layout.width}px;
                        height: ${layout.height}px;
                        top: ${layout.top}px;
                        left: ${layout.left}px;`;
            },
            //拖拽初始化
            drag(event, flag, layout) {
            	this.specify = false;
                this.dragStart(event, flag, layout);
                document.onmousemove = ($event) => {
                    this.dragOver($event);
                };
                document.onmouseup = ($event) => {
                    this.drop($event, flag, layout);
                    document.onmousemove = null;
                    document.onmouseup = null;
                };
            },
            //开始拖拽
            dragStart(event, flag, layout) {
				//console.log(event);
				this.specify = false;
                const index = this.layoutList.indexOf(layout);
                const canvas = $('.canvas');
                const curEl = canvas.find('.layout').eq(index);

                curEl.addClass('current');
                this.position.clientX = event.clientX;
                this.position.clientY = event.clientY;
                this.position.$clientX = event.clientX;
                this.position.$clientY = event.clientY;
                this.curLayout = layout;
                //this.layoutList[blgIndex] = this.layout;
                this.flag = flag;
            },
            //拖动中
            dragOver(event) {
                const offsetX = (event.clientX - this.position.clientX); //鼠标实时水平移动距离
                const offsetY = (event.clientY - this.position.clientY); //鼠标实时垂直移动距离

                let layout = this.curLayout;

                this.position.clientX = event.clientX;
                this.position.clientY = event.clientY;
                if (this.flag) { //拖动
                    layout.left = layout.left + offsetX;
                    layout.top = layout.top + offsetY;
                } else { //缩放
                    layout.width = layout.width + offsetX;
                    layout.height = layout.height + offsetY;
                }
            },
            //拖动结束
            drop(event, flag, layout) {

                const horizonNum = this.svg.horizonNum;
                const index = this.layoutList.indexOf(layout); //当前布局索引
                const width = this.rect.width; //格子宽度
                const height = this.rect.height; //格子高度
                const space = this.svg.space; //格子间距
                const $offsetX = (event.clientX - this.position.$clientX); //鼠标释放前水平移动距离
                const $offsetY = (event.clientY - this.position.$clientY); //鼠标释放前垂直移动距离
                const moveX = $offsetX % (width + space); //水平方向移动距离
                const stepX = parseInt($offsetX / (width + space)); //水平方向移动格子数量
                const moveY = $offsetY % (height + space); //垂直方向移动距离
                const stepY = parseInt($offsetY / (height + space)); //垂直方向移动格子数量
                $(".layout").removeClass('current'); //移除拖拽放大样式
                //边界及碰撞检测
                if (!this.impactDetect(index) && !this.boundaryDetect(layout)) {
                    if (this.flag) { //拖动
                        layout.offsetLeft = layout.originOffsetLeft + stepX + Math.round((moveX - space) / width);
                        layout.offsetTop = layout.originOffsetTop + stepY + Math.round((moveY - space) / height);
                        if (layout.offsetLeft < 0 || (layout.offsetLeft + layout.col) > horizonNum) {
                            layout.offsetLeft = layout.originOffsetLeft;
                        }
                        if (layout.offsetTop < 0) {
                            layout.offsetTop = layout.originOffsetTop;
                        }
                        this.calculatBackground(layout);
                    } else { //放大
                        layout.col = layout.originCol + stepX + Math.round((moveX - space) / width);
                        layout.row = layout.originRow + stepY + Math.round((moveY - space) / height);
                        if (layout.col < this.layout.col || (layout.offsetLeft + layout.col) > horizonNum) {
                            layout.col = layout.originCol;
                        }
                        if (layout.row < this.layout.row) {
                            layout.row = layout.originRow;
                        }
                        this.calculatBackground(layout);
                       
                    }

                    this.position.clientX = event.clientX;
                    this.position.clientY = event.clientY;
                    this.position.$clientX = event.clientX;
                    this.position.$clientY = event.clientY;
                } else {
                    layout.col = layout.originCol;
                    layout.row = layout.originRow;
                    layout.offsetLeft = layout.originOffsetLeft;
                    layout.offsetTop = layout.originOffsetTop;
                }
                this.initLayout();
                this.specify = true;
                //this.boundaryDetect(layout);

            },
            //重新计算背景
	        calculatBackground(layout) {
	            let verticalNum = this.getVerticalNum();
				//console.log("verticalNum:"+verticalNum);
				//console.log("this.layout.row:"+this.layout.row);
	            if(layout.offsetTop+layout.row>=verticalNum){
	                verticalNum += this.layout.row;
	            }else if(layout.offsetTop+layout.row+this.layout.row<verticalNum){
	
	                if(verticalNum>this.svg.verticalNum){
	                    verticalNum = verticalNum - this.layout.row;
	                }
	            }
				
	            this.svg.verticalNum = verticalNum;
	            this.initBackground();
	            this.initLayout();
	        },
	        //获取最大画布高度
	        getVerticalNum() {
	            let verticalNum = this.svg.verticalNum;
	            //console.log("verticalNum:"+verticalNum);
	            this.layoutList.forEach((layout)=>{
	            	//console.log(layout.offsetTop+layout.row);
	                if(verticalNum<(layout.offsetTop+layout.row)){
	                    verticalNum = layout.offsetTop+layout.row
	                }
	            });
				//console.log("verticalNum:"+verticalNum);
	            /*if(verticalNum>=(this.svg.verticalNum-this.layout.row)){
	                verticalNum += this.layout.row;
	            }*/
	            if(this.specify){
	                if(verticalNum<(this.layout.offsetTop+this.layout.row)){
	                    verticalNum = this.layout.offsetTop+this.layout.row
	                }
	            }
	
	            return verticalNum;
	        },
            specifyPosition(event) { //会产生位置误差
                console.log('specifyPosition()');
                let flag = true;
                let layout = this.plain(this.layout);
               
                const width = this.rect.width; //格子宽度
                const height = this.rect.height; //格子高度
                const space = this.svg.space; //格子宽度
                const offsetX = event.offsetX;
                const offsetY = event.offsetY;
                const stepX = parseInt(offsetX / (width + space)); //水平方向移动格子数量
                const stepY = parseInt(offsetY / (height + space - 1)); //水平方向移动格子数量

                let occupyPosition = this.getOccupyPosition();
                let allPosition = this.getAllPosition();

                layout.offsetLeft = stepX;
                layout.offsetTop = stepY;

                let curPosition = this.getCurPosition(layout);
                let temp = {
                    offsetLeft: stepX,
                    offsetTop: stepY
                }

                temp = JSON.stringify(temp);

                if (allPosition.indexOf(temp) > -1) {
                    if (this.arrayIntersect(occupyPosition, curPosition)) {
                        flag = false;
                    }
                } else {
                    flag = false;
                }
                if (flag&&this.specify) {           
                    this.layout = layout;
                    this.layoutList.push(layout);
                    this.initLayout();
                    this.initBackground();

                }
            },
            //获取获取画布第一个符合要求的坐标
            getEmptyPosition() {
                const $this = this;

                let position = {
                    offsetLeft: 0,
                    offsetTop: 0
                }
                let occupyPosition = this.getOccupyPosition();
                let allPosition = this.getAllPosition();

                for (let i = 0; i < allPosition.length; i++) {
                    let pos = allPosition[i];
                    if (occupyPosition.indexOf(pos) === -1) {
                        let curPosition = $this.getCurPosition(JSON.parse(pos));
                        if (!this.arrayIntersect(occupyPosition, curPosition)) {
                            position = pos;
                            return JSON.parse(position);
                        }
                    }
                }
            },
            //判断两个数组是否有交集
	        arrayIntersect(a,b) {
	            let include =false;
	
	            a.forEach((aItem)=>{
	                b.forEach((bItem)=>{
	                    if(a.includes(bItem)){
	                        include = true;
	                    }
	                });
	            });
	
	            return include;
	        },
            //根据左上角坐标获取布局所有坐标
            getCurPosition(pos) {
                const $this = this;

                let position = [];

                for (let y = 0; y < $this.layout.row; y++) {
                    for (let x = 0; x < $this.layout.col; x++) {
                        let pop = {};
                        pop.offsetLeft = pos.offsetLeft + x;
                        pop.offsetTop = pos.offsetTop + y;
                        position.push(JSON.stringify(pop));
                    }
                }

                return position;
            },
            //获取整个画布所有可用坐标点
            getAllPosition() {
                const $this = this;

                let position = [];
                for (let y = 0; y < this.svg.verticalNum; y++) {
                    for (let x = 0; x < this.svg.horizonNum; x++) {
                        if ((x + $this.layout.col) <= this.svg.horizonNum && (y + $this.layout.row) <= this.svg.verticalNum) {
                            let pop = {};
                            pop.offsetLeft = x;
                            pop.offsetTop = y;
                            position.push(JSON.stringify(pop));
                        }
                    }
                }

                return position;
            },
            //获取已经被占用的坐标
            getOccupyPosition() {
                let position = [];

                this.layoutList.forEach((layout) => {
                    for (let x = 0; x < layout.col; x++) {
                        for (let y = 0; y < layout.row; y++) {
                            let pop = {}
                            pop.offsetLeft = layout.offsetLeft + x;
                            pop.offsetTop = layout.offsetTop + y;
                            position.push(JSON.stringify(pop));
                        }
                    }
                });

                return position;
            },
            //边界检测
            boundaryDetect(layout) {
                let boundary = false;

                const horizonNum = this.svg.horizonNum;
                const verticalNum = this.svg.verticalNum;

                if (layout.offsetTop < 0 || layout.offsetLeft < 0) {
                    //console.warn("超出边界了");
                    boundary = true;
                }

                if (layout.offsetLeft + layout.col > horizonNum) {
                    //console.warn("超出边界了");
                    boundary = true;
                }
                if (layout.offsetTop + layout.row > verticalNum) {
                    boundary = true;
                }

                return boundary;
            },
            //检测当前移动或者拖拽布局是否与其他布局重叠
            impactDetect(index) {
                const canvasEl = $('.canvas');
                const el1 = canvasEl.find('.layout').eq(index);
                const $this = this;

                let impact = false;

                for (let i = 0; i < canvasEl.find('.layout').length; i++) {
                    if (index !== i) {
                        const el2 = canvasEl.find('.layout').eq(i);
                        if ($this.touchDetect(el1, el2, index, i).impact) {
                            impact = true;
                        }
                    }
                }

                return impact;
            },
            //两个元素碰撞检测
            touchDetect(el1, el2, index1, index2) {
                let touch = {};

                const t1 = el1.offset().top;
                const l1 = el1.offset().left;
                const r1 = el1.offset().left + el1.width();
                const b1 = el1.offset().top + el1.height();

                const t2 = el2.offset().top;
                const l2 = el2.offset().left;
                const r2 = el2.offset().left + el2.width();
                const b2 = el2.offset().top + el2.height();

                if (b1 < t2 || l1 > r2 || t1 > b2 || r1 < l2) { // 表示没碰上
                    //console.log("恭喜您，没碰上b!");
                    touch.impact = false;
                    touch.index1 = index1;
                    touch.index2 = index2;
                } else {
                    touch.impact = true;
                    touch.index1 = index1;
                    touch.index2 = index2;
                    //console.warn(`layout${index1}和layout${index2}碰上了。。。。。。。。`);
                }

                return touch;
            }
        }
    });
}